﻿using System.Collections.Generic;

namespace System.Xml
{
    /// <summary>
    /// xml值读取模式
    /// </summary>
    public enum XmNodeValueMode : byte
    {
        Auto = 0,
        Value = 1,
        InnerXml = 2,
        OuterXml = 3,
        InnerText = 4
    }

    /// <summary>
    /// xmlNode的扩展方法
    /// </summary>
    public static class XmlNodeExtensions
    {
        private static string ReadNodeValue(XmlNode node, XmNodeValueMode mode)
        {
            if (node == null) return null;
            switch (mode)
            {
                case XmNodeValueMode.Auto:
                    if (string.IsNullOrWhiteSpace(node.Value))
                    {
                        if (string.IsNullOrWhiteSpace(node.InnerXml))
                        {
                            if (string.IsNullOrWhiteSpace(node.OuterXml))
                            {
                                if (string.IsNullOrWhiteSpace(node.InnerText)) return null;
                                else return node.InnerText;
                            }
                            else return node.OuterXml;
                        }
                        else return node.InnerXml;
                    }
                    else return node.Value;
                case XmNodeValueMode.Value:
                    return node.Value;
                case XmNodeValueMode.InnerXml:
                    return node.InnerXml;
                case XmNodeValueMode.OuterXml:
                    return node.OuterXml;
                case XmNodeValueMode.InnerText:
                    return node.InnerText;
            }
            return null;
        }

        public static XmlNode ReadAsNode(this XmlNode node, string xpath, XmNodeValueMode mode = XmNodeValueMode.Auto)
        {
            var xml = ReadFirst(node, xpath, mode);
            if (string.IsNullOrWhiteSpace(xml)) return null;
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            return doc;
        }
        /// <summary>
        /// 读取一个xml值
        /// </summary>
        /// <param name="node"></param>
        /// <param name="xpath"></param>
        /// <returns></returns>
        public static string ReadFirst(this XmlNode node, string xpath, XmNodeValueMode mode = XmNodeValueMode.Auto)
        {
            if (node == null) return null;
            if (string.IsNullOrWhiteSpace(xpath)) return null;
            var _node = node.SelectSingleNode(xpath);
            if (_node == null) return null;
            return ReadNodeValue(_node, mode);
        }
        /// <summary>
        /// 读取xml文件
        /// </summary>
        /// <param name="node"></param>
        /// <param name="xpath"></param>
        /// <param name="isValue">如果为true则读取Value属性,否则读取OuterXml</param>
        /// <returns></returns>
        public static IEnumerable<string> ReadAll(this XmlNode node, string xpath, XmNodeValueMode mode = XmNodeValueMode.Auto)
        {
            if (node == null) yield return null;
            if (string.IsNullOrWhiteSpace(xpath)) yield return null;
            var nodes = node.SelectNodes(xpath);
            if (nodes == null) yield return null;
            foreach (XmlNode _node in nodes)
            {
                yield return ReadNodeValue(_node, mode);
            }
        }
        private static XmlNode CreateXmlNode(string xml)
        {
            XmlDocument document = new XmlDocument();
            document.LoadXml(xml);
            return document;
        }
        /// <summary>
        /// 读取xml文件
        /// </summary>
        /// <param name="node"></param>
        /// <param name="xpath"></param>
        /// <param name="isValue">如果为true则读取Value属性,否则读取OuterXml</param>
        /// <returns></returns>
        public static IEnumerable<XmlNode> ReadComplex(this XmlNode node, string xpath, XmNodeValueMode mode = XmNodeValueMode.Auto)
        {
            if (node == null) yield return null;
            if (string.IsNullOrWhiteSpace(xpath)) yield return null;
            var nodes = node.SelectNodes(xpath);
            if (nodes == null) yield return null;
            foreach (XmlNode _node in nodes)
            {
                yield return CreateXmlNode(ReadNodeValue(_node, mode));
            }
        }
    }
}
